import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Calendar;



import mms.farina.thecell.messages.CustomMessage;




class BaseServer {

	protected static final String REG_RES_WAIT  = "No client in the net";
	protected String lastIp="";
	protected int lastPort=0;
	public String pwd="0";

	
	
	CustomMessage interpretCmd(String ip, int port){
		

		CustomMessage response=null;
		
		
		if(lastIp.isEmpty()){
			lastIp=ip;
			lastPort=port;
			response=new CustomMessage(CustomMessage.MESSAGE_TYPE_POLLRESPONSE, "", 0, ip, port);
		}
		else if(lastIp.equals(ip) && lastPort==port)response=new CustomMessage(CustomMessage.MESSAGE_TYPE_POLLRESPONSE, "", 0, ip, port);
		else{
		
		response=new CustomMessage(CustomMessage.MESSAGE_TYPE_POLLRESPONSE, lastIp, lastPort, ip, port);
		lastIp=ip;
		lastPort=port;
		}
		
		return response;
	}
	
	CustomMessage authentication(CustomMessage m){
		
		CustomMessage response=null;
		
		if(m.getType().equals(CustomMessage.MESSAGE_TYPE_ATUHREQ)){
			response=new CustomMessage(CustomMessage.MESSAGE_TYPE_ATUHRES, "");
		}
		else if(m.getType().equals(CustomMessage.MESSAGE_TYPE_ATUHREQ2)){
				if(pwd.equals(m.getSender_nick()))response=new CustomMessage(CustomMessage.MESSAGE_TYPE_ATUHRES2, "ACK");
				else response=new CustomMessage(CustomMessage.MESSAGE_TYPE_ATUHRES2, "NACK");

		}
		else if(m.getType().equals(CustomMessage.MESSAGE_TYPE_ATUHREQ3)){
				response=new CustomMessage(CustomMessage.MESSAGE_TYPE_ATUHRES3, pwd);
		}
		else{
			System.out.println("Messaggio Errato");
			response=new CustomMessage(CustomMessage.MESSAGE_TYPE_ATUHRES3, "NACK");
		}
		
		return response;
	}



}


class UdpServer extends BaseServer {

	DatagramSocket socket = null;
	int RESET_TIME=500*1000;


	public UdpServer() throws IOException {
		this(4450);
	}
	
	public UdpServer(int port, String pwd) throws IOException {
		this(port);
		super.pwd=pwd;
		
	}


	public UdpServer(int port) throws IOException {
		super();
		socket = new DatagramSocket(port);
	}


	public void run() {
		byte[] buf;
		CustomMessage request, response;
		DatagramPacket packet;
		
		
		while (true) {

			buf = new byte[1024];
			packet = new DatagramPacket(buf, buf.length);

			try {
				
				socket.setSoTimeout(RESET_TIME);
				socket.receive(packet);
				request = MySerialization.DeSerializeSimpleCustomMessage(buf);
				
				
				if(!request.getType().equals(CustomMessage.MESSAGE_TYPE_POLL) &&
				   !request.getType().equals(CustomMessage.MESSAGE_TYPE_ATUHREQ) &&
				   !request.getType().equals(CustomMessage.MESSAGE_TYPE_ATUHREQ2) &&
				   !request.getType().equals(CustomMessage.MESSAGE_TYPE_ATUHREQ3) ) continue;
				
				System.out.println(request.getType());

				InetAddress address = packet.getAddress();
				
				int port = packet.getPort();
				if(request.getType().equals(CustomMessage.MESSAGE_TYPE_POLL)) response = interpretCmd(address.getHostAddress(), packet.getPort());
				else response=authentication(request);
				System.out.println(response.getNeighbour_ip()+"-->"+response.getNeighbour_port()+"//"+response.getSender_ip()+"-->"+response.getSender_port());
				System.out.println(response.getType()+"//"+response.getSender_nick());
				buf = MySerialization.SerializeSimpleMessage(response);
				
				packet = new DatagramPacket(buf, buf.length, address, port);
				socket.send(packet);

			} 
			catch (InterruptedIOException e) {
				lastIp="";
				lastPort=0;
				System.out.println("Server Parameters Flushed");
			}
			catch (IOException e) {
				e.printStackTrace();
			}
		}
		
	}


	@Override
	protected void finalize() throws Throwable {
		socket.close();
		super.finalize();
	}

}

